package com.sy.core.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.HashMap;
import java.util.Map;

public class SpringUtils implements ApplicationContextAware {

    private static Logger logger = LoggerFactory.getLogger(SpringUtils.class);

    private static ApplicationContext applicationContext;

    private static Map<String, Object> DYNAMIC_BEAN_CACHE = new HashMap<String, Object>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    public static Object getBean(Class c) throws BeansException {
        return applicationContext.getBean(c);
    }


    public static Object getBean(String c) throws BeansException {
        return applicationContext.getBean(c);
    }

    public static Object getDynamicBean(String beanName) {
        Object executor = DYNAMIC_BEAN_CACHE.get(beanName);
        try {
            if (executor == null) {
                Class clazz = Class.forName(beanName);
                executor = BeanUtils.instantiateClass(clazz);
                autowireBean(executor);
                putDynamicBean(executor);
                logger.debug("创建实例,并动态注入和缓存:" + beanName);
            } else {
                logger.debug("从缓存中读取实例:" + beanName);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return executor;
    }

    public static void autowireBean(Object bean) {
        autowireBean(bean, applicationContext);
    }

    /**
     * 调用spring注入新创建对象的相关属性(根据属性名进行注入)
     *
     * @param bean
     * @param appContext
     */
    private static void autowireBean(Object bean, ApplicationContext appContext) {
        autowireBean(bean, appContext, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
    }

    /**
     * 调用spring注入新创建对象的相关属性
     *
     * @param bean
     * @param appContext
     * @param autowireMode
     */
    private static void autowireBean(Object bean, ApplicationContext appContext, int autowireMode) {
        if (bean == null || appContext == null) {
            return;
        }

        AutowireCapableBeanFactory factory = appContext.getAutowireCapableBeanFactory();
        factory.autowireBeanProperties(bean, autowireMode, false);

        String beanName = bean.getClass().getName();
        factory.initializeBean(bean, beanName);
    }

    public static void putDynamicBean(Object o) {
        DYNAMIC_BEAN_CACHE.put(o.getClass().getName(), o);
    }
}
